package model.data;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedList;

public class DataSource {
	private LinkedList<Measurement> data;
	private int crossValidationParts;
	private DataSet trainingSet = new DataSet();
	private DataSet validationSet = new DataSet();

	public DataSource(LinkedList<Measurement> list) {
		data = list;
	}

	/**
	 *  Metoda dzieląca dane źródłowe na dwa DataSet'y
	 * 
	 *        Dane są dzielone w zależności od punktu podziału, który jest
	 *        podawany jako argument wywałania metody
	 */

	public void divide(int separationPoint) {
		if (data.size() > separationPoint) 
		{
			for (int i = 0; i < separationPoint; i++) {
				trainingSet.add(data.get(i));
			}
			for (int i = separationPoint; i < data.size(); i++) {
				validationSet.add(data.get(i));
			}
		}
	}

	public void divide(int start, int stop) {
		for (int i = 0; i < data.size(); i++) {
			if (i >= start && i < (stop % data.size())) {
				trainingSet.add(data.get(i));
			} else
				validationSet.add(data.get(i));
		}
	}

	// jeśli chcemy przeprowadzić kroswalidację, najpierw wywołujemy metodę
	// crossValidate(),
	// potem c

	public void crossValidate(int parts) {
		crossValidationParts = parts;
	}

	// metoda wyznacza dane przy kolejnym podziale kroswalidacji
	public void computeSet(int part) {
		if (part < crossValidationParts) {
			validationSet = new DataSet();
			trainingSet = new DataSet();
			for (int i = 0; i < data.size(); i++) {
				if ((i >= (part * (data.size() / crossValidationParts)))
						&& (i < (part + 1)
								* (data.size() / crossValidationParts))) {
					validationSet.add(data.get(i));
				} else {
					trainingSet.add(data.get(i));
				}
			}
		} else
			System.out
					.println("Nie możesz wyznaczać kolejnych podziałów w procesie kroswalidacji");
	}

	public void saveInFile(String fileName) {

		try {
			FileWriter fstream = new FileWriter(fileName);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("ID ; Czas[ms] ; Dzien_tygodnia ; Miesiac ; Czas[min] ; Natezenie_ruchu ; Srednia_predkosc ; Temp_2m ; Temp_odczuwalna ; Temp_20cm; Temp_naw_0cm ; Temp_naw_-5; Temp_pkt_rosy ; Wilgotnosc_2m; Opady ; Przewodnosc_naw ; Wiatr ; Wiatr_max ; Kier_wiatru\n");

			for (int i = 0; i < data.size(); i++) {

				// System.out.println(i);
				Measurement measurement = data.get(i);
				double[] tmpArray = measurement.getValues();
				for (int j = 0; j < tmpArray.length; j++) {
					if (j == 0)
						out.write((int)tmpArray[j] + ";");
					else if (j == 1)
						out.write((long) tmpArray[j] + ";");
					else
						out.write(tmpArray[j] + ";");
				}
				out.write('\n');
			}
			out.close();
		} catch (IOException e) {
			System.err.println("Error: " + e.getMessage());
		}

	}

	/**
	 * @brief Metoda zwracająca zestaw treningowy.
	 * 
	 *        Metoda zwraca Listę ze zbiorem treningowym.
	 */

	public DataSet getTrainingSet() {
		return trainingSet;
	}

	/**
	 * @brief Metoda zwracająca zestaw testujący.
	 * 
	 *        Metoda zwraca Listę ze zbiorem testującym.
	 */

	public DataSet getValidationSet() {
		return validationSet;
	}

}
